#!/usr/bin/env python
# This is the reminder class, helping you organize and overview your personal notes.
# Copyright (C) 2011  Frank Uhlig
# 
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
# 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

import os,commands,shutil

class Reminder:

    def __init__(self, kind):
        """there will be documentation here, soon
        """

        self.kind = kind
        self.database=os.environ["HOME"]+'/.re%sr' %self.kind
        if not os.path.exists(self.database):
            print '\n Database does not exist. \n Will create a new one "%s", could take a few seconds. \n' % self.database
            open(self.database, 'w').close()
            self.update_db()
        else:
            self.read_db()

    def update_db(self):
        """update database with all reminders and notes existing around the
        perimeters of the system"""

        cmd='updatedb -l 0 -o $HOME/.re%srdb -U $HOME/' %self.kind
        os.system(cmd)

        cmd="locate -d $HOME/.re%srdb '*.%s'" %(self.kind, self.kind)
        self.notes = commands.getoutput(cmd).split('\n')

        f=open(self.database,'w')
        for note in self.notes:
            f.write(note+'\n')
        f.close()

        return self

    def read_db(self):
        """read in database file without updating it before"""

        self.notes = []
        f = open(self.database)
        lines = f.readlines()
        for line in range(len(lines)):
            try:
                lines[line].index('.%s' %self.kind)
            except ValueError:
                continue
            else:
                self.notes.append(lines[line].replace('\n',''))

    def show_note(self,n):
        """function to display the content of a single note"""
        
        f = open(self.notes[n],'r')
        lines = f.readlines()
        print '\n '+ self.notes[n].split('/')[-1].replace('.%s' %self.kind,'')+':'
        print ' '+(len(self.notes[n].split('/')[-1].replace('.%s' %self.kind,''))+1)*'-'
        print ' (' + self.notes[n].replace('/'+self.notes[n].split('/')[-1],'') + ')'+'\n'
        for line in range(len(lines)):
            print '    '+lines[line].replace('\n','')
        print '\n'

    def list_notes(self):
        """function to display notes in a short and convenient fashion"""
        
        notes = []
        maxl = 0
        for n in range(len(self.notes)):
            notes.append(self.notes[n].split('/')[-1].replace('.%s' %self.kind,''))
            if len(notes[-1]) >maxl:
                maxl = len(notes[-1])

        spacer = '  '
        numb = len(str(len(notes)-1)) + len(spacer)
        leng=40
        empt=' '
        print ' _______________________________________\n ________________NOTES__________________ \n'
        for n in range(len(notes)):
            if len(notes[n]) > leng-numb-len(spacer):
                print (numb-len(str(n)))*empt+str(n)+spacer+(leng-len(notes[n])-numb)*empt+notes[n][:leng-numb-2]
            else:
                print (numb-len(str(n)))*empt+str(n)+(leng-len(notes[n])-numb)*empt+notes[n] #+(maxl-len(notes[n]))*empt #flush right

#other print statements:
#print (numb-len(str(n)))*empt+str(n)+(leng-len(notes[n])-numb-(maxl-len(notes[n]))/2)*empt+notes[n] #+(maxl-len(notes[n]))*empt #concentric
#print (numb-len(str(n)))*empt+str(n)+(leng-len(notes[n])-numb-(maxl-len(notes[n])))*empt+notes[n] #+(maxl-len(notes[n]))*empt #flush left
        print '\n'

    def edit_note(self,n):
        """edit given note n within editor given in system variable $EDITOR"""

        os.system('$EDITOR'+' '+self.notes[n])

    def remove_note(self,n):
        """remove note from database"""

        for cmd in ['rm $HOME/.re%sr' %self.kind,'rm %s' %self.notes[n]]:
            os.system(cmd)

        self.notes.remove(self.notes[n])

        f=open(self.database,'w')
        for note in self.notes:
            f.write(note+'\n')
        f.close()

        return self

def main():
    """program entry point, if run directly"""

    from optparse import OptionParser
    import sys
    import os

    # construct the option parser
    parser = OptionParser(usage='%prog [options]')

    parser.add_option('-s', '--show',
	              dest='show', action='store_true', help='show current reminders and notes')

    parser.add_option('-u', '--update',
	              dest='update', action='store_true', help='update the database of reminders and notes')

    parser.add_option('-e', '--edit',
	              dest='edit', action='store', type='str',
                  nargs=1,
		          help='note or reminder to edit')

    parser.add_option('-c', '--content',
	              dest='content', action='store', type='str',
                  nargs=1,
		          help='show content of note or reminder')

    parser.add_option('-d', '--delete',
	              dest='delete', action='store', type='str',
                  nargs=1,
		          help='delete note or reminder')

    parser.add_option('-l', '--location',
	              dest='location', action='store', type='str',
                  nargs=1,
		          help='show location of note or reminder')

    parser.add_option('-k', '--kind',
                  dest='kind', action='store', type='str',
                  nargs=1,
                  help='which kind of reminder, notes, work,...; kind will be used as marker in the note ending')

    parser.add_option('-b', '--backup',
                  dest='backup', action='store', type='str',
                  nargs=1,
                  help='make a backup of all your notes, argument given is directory where backup should placed')


    # run the option parser and get results
    (options, args) = parser.parse_args()

    # if filename not given, use stdout for output

    if options.kind:
        argchain = len(sys.argv) - 2
    else:
        argchain = len(sys.argv)

    if argchain == 1 or (argchain == 1 and options.kind):
        options.show = True, True
    elif (argchain == 2 and not options.show and not options.update):
        try:
            options.content = sys.argv[-1]
        except ValueError:
            content = False
    #elif options.kind and not options.update and not options.show:
    #    try:
    #        options.content = sys.argv[1]
    #    except ValueError:
    #        content = False


    if options.kind:
        r = Reminder(options.kind)
    else:
        r = Reminder('note')

    if options.update:
        r.update_db()

    if options.show:
        r.list_notes()

    if options.backup is not None:
        for note in r.notes:
            i = 0
            tmpfn = note.split('/')[-1].replace('.%s' %r.kind, '')

            if os.path.exists(options.backup + '/' + tmpfn):
                docopy = False
                while not docopy:
                    if not os.path.exists(options.backup + '/' + tmpfn + '-%i' %i):
                        i += 1
                        docopy = True
                    else:
                        i += 1
            
            fn = options.backup + '/' + tmpfn

            if i != 0:
                fn = fn + '-%i' %i

            shutil.copy(note, fn)

            f = open(fn, 'a')
            f.write('\n###\nnote taken from: %s\n' %note)
            f.close()

    if options.edit is not None:
        try:
            options.edit = int(options.edit)
        except ValueError:
            for n in range(len(r.notes)):
                try:
                    r.notes[n].split('/')[-1].replace('.%s' %r.kind,'').index(options.edit)
                    options.edit = n
                    break
                except ValueError:
                    continue
        try:
            r.edit_note(options.edit)
        except:
            print '\n Note is not existent!!!\n'

    if options.content is not None:
        try:
            options.content = int(options.content)
        except ValueError:
            for n in range(len(r.notes)):
                try:
                    r.notes[n].split('/')[-1].replace('.%s' %r.kind,'').index(options.content)
                    options.content = n
                    break
                except ValueError:
                    continue
        try:
            r.show_note(options.content)
        except:
            print '\n Note is not existent!!!\n'

    if options.delete is not None:
        try:
            options.delete = int(options.delete)
        except ValueError:
            for n in range(len(r.notes)):
                try:
                    r.notes[n].split('/')[-1].replace('.%s' %r.kind,'').index(options.delete)
                    options.delete = n
                    break
                except ValueError:
                    continue
        try:
            r.remove_note(options.delete)
        except:
            print '\n Note is not existent!!!\n'

    if options.location is not None:
        try:
            options.location = int(options.location)
        except ValueError:
            for n in range(len(r.notes)):
                try:
                    r.notes[n].split('/')[-1].replace('.%s' %r.kind,'').index(options.location)
                    options.location = n
                    break
                except ValueError:
                    continue
        try:
            print '\n ' + r.notes[options.location].replace('/'+r.notes[options.location].split('/')[-1],'') + '\n'
        except:
            print '\n Note is not existent!!!\n'

if __name__ == '__main__':
    main()
